package com.jourwon.spring.boot.controller;

import com.jourwon.spring.boot.model.dto.InsertUserDTO;
import com.jourwon.spring.boot.model.dto.UpdateUserDTO;
import com.jourwon.spring.boot.model.dto.UserDTO;
import com.jourwon.spring.boot.model.query.UserQuery;
import com.jourwon.spring.boot.model.vo.CommonPageVO;
import com.jourwon.spring.boot.model.vo.CommonResponseVO;
import com.jourwon.spring.boot.model.vo.UserVO;
import com.jourwon.spring.boot.service.UserService;
import com.jourwon.spring.boot.util.BeanTransformUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.List;

/**
 * 用户controller
 * controller层应尽量遵循RESTful风格，如果是复杂的查询接口，可以考虑使用POST请求，请求参数可以考虑使用对象而不是使用xxx=sss的请求url形式
 * <p>
 * 请求响应规范有两种形式，项目团队根据实际情况进行选择：
 * 1.前端传递vo（请求参数使用xxReqVO，响应参数使用xxRespVO）给接口controller层，接口controller层将vo转为dto传递给service层，
 * service层将dto转为do，然后调用dao层或者mapper层进行数据库增删改查处理，处理完后service层将do转为dto返回给接口controller层，接口controller层将dto转vo，然后将vo传递给前台。
 * <p>
 * 2.前端传递dto（请求参数使用类似InsertUserDTO，UpdateUserDTO，xxUserQuery）给接口controller层，接口controller层将dto传递给service层，
 * service层将dto转为do，然后调用dao层或者mapper层进行数据库增删改查处理，处理完后service层将do转为dto返回给接口controller层，接口controller层将dto转vo，然后将vo传递给前台。
 * <p>
 * 任何API设计都遵循一种叫做“面向资源设计”的原则：
 * 参考：https://mp.weixin.qq.com/s?__biz=MzU3MDAzNDg1MA==&mid=2247506245&idx=1&sn=b8ed8e6b4947c5783014b25c79b10813
 * <p>
 * 资源：资源是数据的一部分，例如：用户
 * 集合：一组资源称为集合，例如：用户列表
 * URL：标识资源或集合的位置，例如：/user
 * <p>
 * 1. 对URL使用kebab-case（短横线小写隔开形式）
 * 例如，如果你想要获得订单列表。
 * 不应该：/systemOrders或/system_orders
 * 应该：/system-orders
 * <p>
 * 2. 参数使用camelCase（驼峰形式）
 * 例如，如果你想从一个特定的商店购买产品。
 * 不应该：/system-orders/{order_id}或者：/system-orders/{OrderId}
 * 应该：/system-orders/{orderId}
 * <p>
 * 3. 指向集合的复数名称
 * 如果你想获得系统的所有用户。
 * 不应该：GET /user或：GET /User
 * 应该：GET /users
 * <p>
 * <p>
 * Service / DAO 层方法命名规约
 * 方法功能	            前缀	                说明
 * 获取单个对象的方法	    get	                getObject
 * 获取多个对象的方法	    list	            复数形式结尾 listObjects
 * 分页查询的方法	        page
 * 获取计数的方法	        count
 * 获取统计的方法	        stat
 * 插入的方法	            save / insert
 * 删除的方法	            remove / delete
 * 修改的方法	            update
 *
 * @author JourWon
 * @date 2022/6/27
 */
@Api(tags = "用户-使用统一响应")
@RestController
@RequestMapping("/users")
public class UserController {

    @Resource
    private UserService userService;

    @PostMapping
    @ApiOperation("新增用户")
    public CommonResponseVO<Integer> insertSelective(@Valid @RequestBody InsertUserDTO insertUserDTO) {
        return CommonResponseVO.success(userService.insertSelective(insertUserDTO));
    }

    @DeleteMapping("/{userId}")
    @ApiOperation("根据主键删除用户")
    public CommonResponseVO<Integer> deleteByPrimaryKey(@PathVariable("userId") Long userId) {
        return CommonResponseVO.success(userService.deleteByPrimaryKey(userId));
    }

    @PutMapping("/{userId}")
    @ApiOperation("根据主键更新用户")
    public CommonResponseVO<Integer> updateByPrimaryKeySelective(@PathVariable("userId") Long userId, @Valid @RequestBody UpdateUserDTO updateUserDTO) {
        updateUserDTO.setUserId(userId);
        return CommonResponseVO.success(userService.updateByPrimaryKeySelective(updateUserDTO));
    }

    @GetMapping("/{userId}")
    @ApiOperation("通过主键获取用户")
    public CommonResponseVO<UserVO> getByPrimaryKey(@PathVariable("userId") Long userId) {
        UserDTO userDTO = userService.getByPrimaryKey(userId);
        return CommonResponseVO.success(BeanTransformUtils.transform(userDTO, UserVO.class));
    }

    @GetMapping
    @ApiOperation("查询所有的用户列表")
    public CommonResponseVO<List<UserVO>> listUsers() {
        List<UserDTO> listUsers = userService.listUsers();
        return CommonResponseVO.success(BeanTransformUtils.transformList(listUsers, UserVO.class));
    }

    @GetMapping("/page")
    @ApiOperation("分页查询用户")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "pageNum", value = "当前页数", dataTypeClass = Integer.class),
            @ApiImplicitParam(name = "pageSize", value = "每页记录数", dataTypeClass = Integer.class),
            @ApiImplicitParam(name = "username", value = "用户名", dataTypeClass = String.class),
            @ApiImplicitParam(name = "mobilePhoneNumber", value = "手机号码", dataTypeClass = String.class),
            @ApiImplicitParam(name = "email", value = "邮箱", dataTypeClass = String.class)
    })
    public CommonResponseVO<CommonPageVO<UserVO>> page(@RequestParam(required = false, defaultValue = "1", value = "pageNum") Integer pageNum,
                                                       @RequestParam(required = false, defaultValue = "10", value = "pageSize") Integer pageSize,
                                                       @RequestParam(required = false, value = "username") String username,
                                                       @RequestParam(required = false, value = "mobilePhoneNumber") String mobilePhoneNumber,
                                                       @RequestParam(required = false, value = "email") String email) {
        UserQuery userQuery = UserQuery.builder().pageNum(pageNum).pageSize(pageSize).username(username)
                .mobilePhoneNumber(mobilePhoneNumber).email(email).build();
        return CommonResponseVO.success(userService.page(userQuery));
    }

    @PostMapping("/page-post")
    @ApiOperation("分页查询用户-复杂查询使用POST请求")
    public CommonResponseVO<CommonPageVO<UserVO>> pagePost(@RequestBody @Valid UserQuery userQuery) {
        return CommonResponseVO.success(userService.page(userQuery));
    }

}
